package item71;

/**
 * 第71条: 慎用延迟初始化
 */
public class Main01 {

    // Normal initialization of an instance field
    // 正常初始化
    private final Main01 main01 = new Main01();

    // Lazy initialization of instance field - synchronized accesssor
    // 实例字段的延迟初始化 - 同步访问
    private Integer value;

    synchronized Integer getValue() {
        if (value == null)
            value = 1;
        return value;
    }

    // lazy initialization holder class idiom for static fields
    private static class FieldHolder {
        static final Long value01 = 1l;
    }
    static Long getValue01() {
        return FieldHolder.value01;
    }


    // double-check idiom for lazy initialization of instance fields
    // 对实例字段的延迟初始化进行双重检查
    private volatile Boolean flag;
    boolean getFlag() {
        Boolean result = flag;
        if (result == null) {  // first check (no locking)
            synchronized (this) {
                result = flag;
                if (result == null) // second check (with locking)
                    flag = result = true;
            }
        }
        return result;
    }

    // 可以接受重复初始化的实例域
    // single-check idiom - can cause repeated initialization!
    private volatile Integer value02;

    private Integer getValue02() {
        Integer result = value02;
        if (result == null)
            value02 = result = 2;
        return result;
    }

    public static void main(String[] args) {

        // 所有初始化方法都是线程安全的。

        // 在大多数情况下，正常的初始化要优先于延迟初始化。

        // 如果利用延迟优化来破坏初始化的循环，就要使用同步访问方法，因为它是最简单、最清楚的替代方法。

        // 正常的初始化和使用了同步访问方法的延迟初始化

        // 如果出于性能考虑而需要对静态域使用延迟初始化，就使用lazy initialization holder class模式。

        // 如果出于性能的考虑而需要对静态域使用延迟初始化，就使用双重检查模式(double-check idiom).


    }

}
